// Code file original author: Martin Lapierre, http://devinstinct.com

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using EntLibContrib.Validation.Validators;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using System.Collections;

namespace EntLibContrib.Validation.Tests.Validators
{
    /// <summary>
    /// Tests <see cref="CollectionCountValidator"/>.
    /// </summary>
    /// <remarks>
    /// This fixture is a spin-off of EntLib's unit tests.
    /// </remarks>
    [TestClass]
    public class CollectionCountValidatorFixture
    {
        [TestMethod]
        public void ReturnFailureForNullCollection()
        {
            CollectionCountValidator validator = new CollectionCountValidator(1, 10);

            ValidationResults validationResults = validator.Validate(null);

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnFailureForNullCollectionThroughNonGenericInterface()
        {
            CollectionCountValidator validator = new CollectionCountValidator(1, 10);

            ValidationResults validationResults = validator.Validate(null);

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionShorterThanMaxLengthForMaxLengthOnlyValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(10);

            ValidationResults validationResults = validator.Validate(GetCollection(5));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsFailureForCollectionShorterThanMaxLengthForMaxLengthOnlyValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(10, true);

            ValidationResults validationResults = validator.Validate(GetCollection(5));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionOneCharShorterThanMaxLengthForMaxLengthOnlyValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(10);

            ValidationResults validationResults = validator.Validate(GetCollection(9));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionAsLongAsMaxLengthForMaxLengthOnlyValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(10);

            ValidationResults validationResults = validator.Validate(GetCollection(10));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsFailureForCollectionAsLongAsMaxLengthForMaxLengthOnlyValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(10, true);

            ValidationResults validationResults = validator.Validate(GetCollection(10));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsSuccessForCollectionLongerThanMaxLengthForMaxLengthOnlyValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(10, true);

            ValidationResults validationResults = validator.Validate(GetCollection(11));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionAsLongAsMinLengthForMinAndMaxLengthValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, 10);

            ValidationResults validationResults = validator.Validate(GetCollection(5));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsFailureForCollectionAsLongAsMinLengthForMinAndMaxLengthValidator()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, 10, true);

            ValidationResults validationResults = validator.Validate(GetCollection(5));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionShorterThanLowerBoundIfLowerBoundIsIgnored()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Ignore, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(2));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsFailureForCollectionShorterThanLowerBoundIfLowerBoundIsIgnored()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Ignore, 10, RangeBoundaryType.Inclusive, true);

            ValidationResults validationResults = validator.Validate(GetCollection(2));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionLongerThanLowerBound()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(7));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsFailureForCollectionLongerThanLowerBound()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive, true);

            ValidationResults validationResults = validator.Validate(GetCollection(7));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionShorterThanLowerBound()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(3));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsFailureForCollectionShorterThanLowerBound()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive, true);

            ValidationResults validationResults = validator.Validate(GetCollection(3));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionWithLengthEqualToLowerBoundIfLowerBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(5));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsFailureForCollectionWithLengthEqualToLowerBoundIfLowerBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive, true);

            ValidationResults validationResults = validator.Validate(GetCollection(5));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionWithLengthEqualToLowerBoundIfLowerBoundIsExclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Exclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(5));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionWithLengthOneShoterThanLowerBoundIfLowerBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(4));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void NegatedReturnsSuccessForCollectionWithLengthOneShoterThanLowerBoundIfLowerBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive, true);

            ValidationResults validationResults = validator.Validate(GetCollection(4));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionWithLengthOneShorterThanLowerBoundIfLowerBoundIsExclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Exclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(4));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionWithLengthOneLongerThanLowerBoundIfLowerBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(6));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionWithLengthOneLongerThanLowerBoundIfLowerBoundIsExclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Exclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(6));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionLongerThanUpperBoundIfUpperBoundIsIgnored()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Ignore);

            ValidationResults validationResults = validator.Validate(GetCollection(12));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionShorterThanUpperBound()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(7));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionLongerThanUpperBound()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(12));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionWithLengthEqualToUpperBoundIfUpperBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(10));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionWithLengthEqualToUpperBoundIfUpperBoundIsExclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Exclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(10));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionWithLengthOneShoterThanLowerBoundIfLUpperBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(9));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsSuccessForCollectionWithLengthOneShorterThanUpperBoundIfUpperBoundIsExclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Exclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(9));

            Assert.IsTrue(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionWithLengthOneLongerThanUpperBoundIfUpperBoundIsInclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(11));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        public void ReturnsFailureForCollectionWithLengthOneLongerThanUpperBoundIfUpperBoundIsExclusive()
        {
            CollectionCountValidator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Exclusive);

            ValidationResults validationResults = validator.Validate(GetCollection(11));

            Assert.IsFalse(validationResults.IsValid);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void CreationWithUpperBoundIsLowerThanLowerBoundAndNeitherBoundIsIgnoredThrows()
        {
            new CollectionCountValidator(15, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Exclusive);
        }

        [TestMethod]
        public void ReturnsFailureForValidationForNonCollectionTargetThroughNonGenericInterface()
        {
            Validator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive);

            Assert.IsFalse(validator.Validate(3).IsValid);
        }

        [TestMethod]
        public void NegatedReturnsSuccessForValidationForNonCollectionTargetThroughNonGenericInterface()
        {
            Validator validator = new CollectionCountValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive, true);

            Assert.IsFalse(validator.Validate(3).IsValid);
        }

        private ICollection GetCollection(int size)
        {
            return new string[size];
        }
    }
}
